package lk.mrt.cse.wihidum.client;

import lk.mrt.cse.wihidum.util.*;
import org.apache.axiom.om.*;
import org.apache.axiom.soap.*;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.*;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.log4j.Logger;

import javax.xml.namespace.QName;
import java.util.Iterator;


/**
 * Created by IntelliJ IDEA.
 * User: Hasini
 * Date: Mar 30, 2010
 * Time: 11:20:36 PM
 * To change this template use File | Settings | File Templates.
 */
public class BrokerRetrievalClient {
    private static final Logger logger = Logger.getLogger(BrokerList.class);

    public void retrieveBrokers(String adminAddress, String subscriberAddress) {
        SOAPEnvelope responseEnvelope = null;
        try {
            ServiceClient serviceClient = new ServiceClient();
            OperationClient opClient = serviceClient.createClient(ServiceClient.ANON_OUT_IN_OP);

            MessageContext outMsg = new MessageContext();
            Options opts = outMsg.getOptions();
            opts.setAction(WihidumConstants.Operations.GET_BROKER);
            opts.setTo(new EndpointReference(adminAddress));

            SOAPEnvelope getBrokerRequestEnvelope = createGetBrokerRequestEnvelope(subscriberAddress);
            outMsg.setEnvelope(getBrokerRequestEnvelope);
            opClient.addMessageContext(outMsg);
            opClient.execute(true);
            MessageContext inMsgtCtx = opClient.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);

            responseEnvelope = inMsgtCtx.getEnvelope();
            processGetBrokersMessage(responseEnvelope, WSEventingConstants.ElementNames.GetBrokerResponse);

        }
        catch (Exception e) {
            e.printStackTrace();
        }


    }

    public void processGetBrokersMessage(SOAPEnvelope message, String messageType) {
        OMElement getBrokerResponseElement = message.getBody().getFirstChildWithName(new QName(WSEventingConstants.WIHIDUM_NAMESPACE, messageType));
        OMElement brokerListElement = getBrokerResponseElement.getFirstChildWithName(new QName(WSEventingConstants.WIHIDUM_NAMESPACE, WSEventingConstants.ElementNames.BrokerList));
        //if this is a update message, earlier broker list should be cleared.
        if (!BrokerList.isEmpty()) {
            BrokerList.clearBrokerList();
        }

        for (Iterator<OMElement> brokerElementIterator = brokerListElement.getChildrenWithName(new QName(WSEventingConstants.WIHIDUM_NAMESPACE, WSEventingConstants.ElementNames.Broker)); brokerElementIterator.hasNext();) {
            OMElement brokerElement = brokerElementIterator.next();
            String brokerAddress = brokerElement.getText();
            logger.info("Broker " + brokerAddress + " is added to client's broker list.");
            BrokerList.addBrokerToList(brokerAddress);
        }

    }

    private SOAPEnvelope createGetBrokerRequestEnvelope(String subscriberAddress) {
        SOAPFactory factory = OMAbstractFactory.getSOAP12Factory();
        SOAPEnvelope getBrokerRequestEnvelope = factory.getDefaultEnvelope();
        //declare namespaces
        OMNamespace wsaNS = factory.createOMNamespace(WSEventingConstants.ADDRESSING_NAMESPACE, WSEventingConstants.ADDRESSING_PREFIX);
        getBrokerRequestEnvelope.declareNamespace(wsaNS);
        OMNamespace wihidumNS = factory.createOMNamespace(WSEventingConstants.WIHIDUM_NAMESPACE, WSEventingConstants.WHIDUM_NAMESPACE_PREFIX);
        getBrokerRequestEnvelope.declareNamespace(wihidumNS);
        SOAPHeader soapHeader = getBrokerRequestEnvelope.getHeader();

        OMElement getBrokerElement = factory.createOMElement(WSEventingConstants.ElementNames.GetBroker, wihidumNS);
        OMElement identifierElement = factory.createOMElement(WSEventingConstants.ElementNames.Identifier, wihidumNS);
        identifierElement.setText(subscriberAddress);

        getBrokerElement.addChild(identifierElement);
        getBrokerRequestEnvelope.getBody().addChild(getBrokerElement);

        return getBrokerRequestEnvelope;
    }
}
